library(rgl)
knitr::knit_hooks$set(webgl = hook_webgl)
Scalable Vector Graphics, abbreviated: SVG, is an XML-based file format for static and dynamic vector graphics. It is an open standard of the W3C. Inkscape is an open source vector illustration program that uses the SVG format to store vector graphics. We start our analyses from checking Inkscape installation
This is the Scalable Vector Graphic we want to analyze:
url <- 'https://upload.wikimedia.org/wikipedia/commons/1/1b/Red_Bird.svg'
knitr::include_graphics(url)
As far there is no easy way to import SVG file, convert it into Simple Features and analyze using R. That’s why we gonna use an external powerful and beautiful tool which is Inkscape.
system('inkscape --version', intern = TRUE)
## [1] "Inkscape 1.0.2-2 (e86c870879, 2021-01-15)"
Function to convert SVG into DXF
is_url <- function(path){
grepl("^https?://", path)
}
download_svg <- function(url){
filename = tempfile("inx", fileext = ".svg")
download.file(url, filename)
return(filename)
}
inx_extension <- function(input, extension, ext){
path = system('inkscape --system-data-directory', intern = TRUE)
inkscape_extensions_path = paste(path, "\\extensions", sep = "")
inkscape_python_home = paste(gsub("\\share\\inkscape", "", path, fixed = T), "\\bin", sep = "")
if(is_url(input)) {
input_file_path = download_svg(input)
} else {
input_file_path = tempfile("inx")
file.copy(input, input_file_path)
}
output = tempfile("inx", fileext = ext)
command = tempfile(pattern = "inx_", fileext = ".bat")
'@ECHO OFF
cd %s
python.exe "%s" --output="%s" "%s"' %>% sprintf(
inkscape_python_home,
paste(inkscape_extensions_path, extension, sep = "\\"),
output,
input_file_path) %>% writeLines(command)
system(command)
output
}
with it’s Linux equivalent:
inx_extension <- function(input, extension, ext){
path = system('inkscape --system-data-directory', intern = TRUE)
inkscape_extensions_path = paste(path, "/extensions", sep = "")
if(is_url(input)) {
input_file_path = download_svg(input)
} else {
input_file_path = tempfile("inx")
file.copy(input, input_file_path)
}
output <- tempfile("inx", fileext = ext)
command <- sprintf('python %s --output="%s" "%s"', paste(inkscape_extensions_path, extension, sep = "/"), output, input_file_path)
system(command, intern = TRUE)
output
}
logo <- inx_extension(input = url, extension = "dxf12_outlines.py", ext =".dxf") %>%
st_read() %>%
select(geometry) %>% st_union() %>% st_polygonize() %>%
first()
## Reading layer `entities' from data source
## `C:\Users\jacek\AppData\Local\Temp\RtmpewC6lM\inx36a846335bc3.dxf'
## using driver `DXF'
## Simple feature collection with 8654 features and 6 fields
## Geometry type: LINESTRING
## Dimension: XY
## Bounding box: xmin: 238.9009 ymin: -837.4039 xmax: 1105.521 ymax: 40.07607
## CRS: NA
logo %>% ggplot() +
geom_sf()
result <- st_sfc() %>% st_sf(geometry = .)
for(i in c(1: length(logo))) {
tmp <- logo %>%
nth(i) %>%
st_sfc() %>% st_sf(geometry = .) %>% mutate(facet = i)
result <- tmp %>% bind_rows(result)
}
result %>% ggplot() +
geom_sf() +
geom_sf_label(aes(label = facet)) +
theme_void()
result %>% plot_ly(split = ~facet)
## No trace type specified:
## Based on info supplied, a 'scatter' trace seems appropriate.
## Read more about this trace type -> https://plotly.com/r/reference/#scatter
result %>% st_write("Red_Bird.shp", append=FALSE)
## Deleting layer `Red_Bird' using driver `ESRI Shapefile'
## Writing layer `Red_Bird' to data source `Red_Bird.shp' using driver `ESRI Shapefile'
## Writing 93 features with 1 fields and geometry type Polygon.
logo <- st_read("./Red_Bird.shp") %>% filter(!facet %in%
c(3:55, 56:60, 81)) %>% st_union()
## Reading layer `Red_Bird' from data source
## `C:\Users\jacek\JacekPardyak.github.io\inkscaper\Red_Bird.shp'
## using driver `ESRI Shapefile'
## Simple feature collection with 93 features and 1 field
## Geometry type: POLYGON
## Dimension: XY
## Bounding box: xmin: 238.9009 ymin: -837.4039 xmax: 1105.521 ymax: 40.07607
## CRS: NA
logo %>% ggplot() +
geom_sf() +
theme_void()
result <- st_read("./Red_Bird.shp") %>% filter(!facet %in%
c(3:55, 56:60, 81)) %>% st_union() %>% st_sfc() %>% st_sf()
## Reading layer `Red_Bird' from data source
## `C:\Users\jacek\JacekPardyak.github.io\inkscaper\Red_Bird.shp'
## using driver `ESRI Shapefile'
## Simple feature collection with 93 features and 1 field
## Geometry type: POLYGON
## Dimension: XY
## Bounding box: xmin: 238.9009 ymin: -837.4039 xmax: 1105.521 ymax: 40.07607
## CRS: NA
result
## Simple feature collection with 1 feature and 0 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: 238.9009 ymin: -837.4039 xmax: 1105.521 ymax: 40.07607
## CRS: NA
## geometry
## 1 MULTIPOLYGON (((792.516 -82...
result %>% ggplot() +
geom_sf()
result
## Simple feature collection with 1 feature and 0 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: 238.9009 ymin: -837.4039 xmax: 1105.521 ymax: 40.07607
## CRS: NA
## geometry
## 1 MULTIPOLYGON (((792.516 -82...
grid_spacing = 10
grid <- result %>% st_make_grid(what = "centers", cellsize = c(grid_spacing, grid_spacing)) %>%
st_sf()
heights <- st_join(grid, (result %>% select(geometry) %>% mutate(Z = 1))) %>% replace(is.na(.), 0)
z <- heights %>% st_coordinates() %>% as_tibble() %>%
bind_cols(heights %>% st_drop_geometry()) %>%
mutate(X = round(X,1)) %>%
mutate(Y = round(Y,1)) %>% pivot_wider(names_from = Y, values_from = Z) %>%
column_to_rownames("X") %>% as.matrix()
x <- 1:nrow(z)
y <- 1:ncol(z)
colorlut <- c("#F2F2F2", "#E34234") #"#ECB176",
col <- colorlut[ z - min(z) + 1 ] # assign colors to heights for each point
#open3d()
surface3d(x, y, z, color = col, back = "lines")
#e34234
#close3d()
library(gganimate)
result_1 <- st_read("./Red_Bird.shp") %>% filter(!facet %in%
c(3:55, 56:60, 81)) %>% st_union() %>% st_sfc() %>% st_sf() %>%
mutate(facet = 1)
## Reading layer `Red_Bird' from data source
## `C:\Users\jacek\JacekPardyak.github.io\inkscaper\Red_Bird.shp'
## using driver `ESRI Shapefile'
## Simple feature collection with 93 features and 1 field
## Geometry type: POLYGON
## Dimension: XY
## Bounding box: xmin: 238.9009 ymin: -837.4039 xmax: 1105.521 ymax: 40.07607
## CRS: NA
result_2 <- st_read("./Red_Bird.shp") %>% filter(facet %in%
c(3:55, 56:60, 81)) %>% st_union() %>% st_sfc() %>% st_sf() %>%
mutate(facet = 2)
## Reading layer `Red_Bird' from data source
## `C:\Users\jacek\JacekPardyak.github.io\inkscaper\Red_Bird.shp'
## using driver `ESRI Shapefile'
## Simple feature collection with 93 features and 1 field
## Geometry type: POLYGON
## Dimension: XY
## Bounding box: xmin: 238.9009 ymin: -837.4039 xmax: 1105.521 ymax: 40.07607
## CRS: NA
result <- result_1 %>% bind_rows(result_2)
result %>% ggplot() +
geom_sf() +
transition_states(
facet,
transition_length = 2,
state_length = 1
) +
enter_fade() +
exit_shrink() +
ease_aes('sine-in-out')